
# $Id: PerlUtil.pm 150 2013-04-13 06:15:29Z chengxin.cai $

package PerlUtil;

use strict;
use base 'Exporter';

use Carp;
use Time::HiRes;
use Sub::Installer;

use threads;

our @EXPORT_OK = qw(
    runForSeconds
    time_it
    gen_getter
    gen_setter
);

our @EXPORT = (@EXPORT_OK);

sub runForSeconds {
    my $interval = shift;
    my $proc = shift;

    croak "The second parameter to runForSeconds must be a code reference"
        if ( ref $proc ne 'CODE' );

    my $th = threads->create( sub { Time::HiRes::sleep($interval); } );

    my $ret = &$proc(@_);

    $th->join();

    return $ret;
}

sub time_it {
    my $title = shift;
    my $fun = shift;

    croak "The second parameter to time_it must be a code reference"
        if (ref $sub ne 'CODE');

    my $start_t = Time::HiRes::time;
    my @ret = &$fun(@_);

    my $end_t = Time::HiRes::time;

    return ($end_t - $start_t, @ret);
}

my $__install_handler = sub {
    my ( $pkg, $handler, $code ) = @_;

    if ( !$pkg->can($handler) ) {
        $pkg->install_sub( { $handler => $code } );
    }
};

###generate the getter function for pkg::attr
sub gen_getter {
    my ( $pkg, $getter ) = @_;

    &$__install_handler( $pkg, $getter, sub { &{$_[0]}( $getter ); } );
}

###generate the setter function for pkg::attr
sub gen_setter {
    my ( $pkg, $setter ) = @_;

    &$__install_handler( $pkg, $setter, 
                         sub { &{ &{$_[0]}($setter) }( $_[1] ); } );
}

1;
